/**
 * Copyright 2009 Sergio Bossa
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package com.googlecode.actorom.support;

import com.googlecode.actorom.ThreadingPolicy;
import com.googlecode.actorom.impl.core.reactor.DefaultMessageQueue;
import com.googlecode.actorom.impl.core.reactor.MessageDemultiplexer;
import com.googlecode.actorom.impl.core.reactor.MessageDispatcher;
import com.googlecode.actorom.impl.core.reactor.MessageQueue;
import com.googlecode.actorom.impl.core.reactor.green.GreenMessageDemultiplexer;
import com.googlecode.actorom.impl.core.reactor.green.GreenMessageDispatcher;
import com.googlecode.actorom.impl.core.reactor.os.OSMessageDemultiplexer;
import com.googlecode.actorom.impl.core.reactor.os.OSMessageDispatcher;
import net.jcip.annotations.ThreadSafe;

/**
 * Static factory class for creating available {@link com.googlecode.actorom.ThreadingPolicy} objects.
 *
 * @author Sergio Bossa
 */
@ThreadSafe
public class ThreadingPolicies {

    /**
     * Create a {@link com.googlecode.actorom.ThreadingPolicy} that uses green threads: messages are asynchronously
     * dispatched and handled by actors in a single operating-system native thread, so there's no actual concurrency between
     * actors.
     * @return
     */
    public static ThreadingPolicy newGreenThreadingPolicy() {
        return new GreenThreadingPolicy();
    }

    /**
     * Create a {@link com.googlecode.actorom.ThreadingPolicy} that uses operating-system native threads: messages are asynchronously
     * dispatched and handled by actors using a fixed pool of operating-system native threads, establishing a level of concurrency
     * between actors equal to the thread pool size.
     * <br><br>
     * Message dispatching is fair: this will avoid actors starvation, but may lead to poor scalability in applications with large number of messages
     * and short computations.
     * @param threadPoolSize Number of threads in pool.
     * @return
     */
    public static ThreadingPolicy newOSThreadingPolicy(int threadPoolSize) {
        return new OSThreadingPolicy(threadPoolSize, true);
    }

    /**
     * Create a {@link com.googlecode.actorom.ThreadingPolicy} that uses operating-system native threads: messages are asynchronously
     * dispatched and handled by actors using a fixed pool of operating-system native threads, establishing a level of concurrency
     * between actors equal to the thread pool size.
     * <br><br>
     * Message dispatching can be fair or unfair:
     * <ul>
     * <li>Fair dispatching will avoid actors starvation, but may lead to poor scalability in applications with large number of messages
     * and short computations.</li>
     * <li>Unfair dispatching provides great scalability, but may lead to starving actors, in particular in applications with large number of messages
     * and long computations.</li>
     * </ul>
     * @param threadPoolSize Number of threads in pool.
     * @param fair True for fair dispatching, false for unfair.
     * @return
     */
    public static ThreadingPolicy newOSThreadingPolicy(int threadPoolSize, boolean fair) {
        return new OSThreadingPolicy(threadPoolSize, fair);
    }

    private static class GreenThreadingPolicy implements ThreadingPolicy {

        public MessageDispatcher getMessageDispatcher() {
            return new GreenMessageDispatcher();
        }

        public MessageDemultiplexer getMessageDemultiplexer() {
            return new GreenMessageDemultiplexer();
        }

        public MessageQueue getMessageQueue() {
            return new DefaultMessageQueue();
        }
    }

    private static class OSThreadingPolicy implements ThreadingPolicy {

        private int threadPoolSize;
        private boolean fair;

        public OSThreadingPolicy(int threadPoolSize, boolean fair) {
            this.threadPoolSize = threadPoolSize;
            this.fair = fair;
        }

        public MessageDispatcher getMessageDispatcher() {
            return new OSMessageDispatcher(threadPoolSize, fair);
        }

        public MessageDemultiplexer getMessageDemultiplexer() {
            return new OSMessageDemultiplexer();
        }

        public MessageQueue getMessageQueue() {
            return new DefaultMessageQueue();
        }
    }
}
